#include "CDicomImage.h"
#include "Utilities.h"


CDicomImage::CDicomImage()
    : CBaseImage()
{
}


CDicomImage::~CDicomImage()
{
	
}

BOOL CDicomImage::ParseFile(std::string fn)
{
	std::lock_guard<std::mutex> lg(m_mtx);
	if (!m_parser.Open(fn))
		return FALSE;

    std::string charset = m_parser.GetTagStringValue(0x0008, 0x0005);

	BOOL needTransToGbk = FALSE;
    if (charset == "ISO_IR 192")
		needTransToGbk = TRUE;

    std::string tmp;
	std::string strVal;

	// Patient
    m_patInfo.patId = m_parser.GetTagStringValue(0x0010, 0x0020);
	strVal = m_parser.GetTagStringValue(0x0010, 0x0010);
	if (needTransToGbk)
		m_patInfo.patName = UTF8toA(strVal).c_str();
	else
		m_patInfo.patName = strVal.c_str();
		
    m_patInfo.sex = m_parser.GetTagStringValue(0x0010, 0x0040);
    tmp = m_parser.GetTagStringValue(0x0010, 0x0030);
    if (tmp.length() == 8)
	{
        m_patInfo.birthday = tmp.substr(0, 4);
        m_patInfo.birthday += "-";
        m_patInfo.birthday += tmp.substr(4, 2);
        m_patInfo.birthday += "-";
        m_patInfo.birthday += tmp.substr(6);
	}
	else
		m_patInfo.birthday = tmp;

    m_patInfo.studyAge = m_parser.GetTagStringValue(0x0010, 0x1010);
	m_patInfo.patWeight = m_parser.GetTagFloatValue(0x0010, 0x1030);

	// Study
    m_studyInfo.modality = m_parser.GetTagStringValue(0x0008, 0x0060);
    m_studyInfo.studyInsUid = m_parser.GetTagStringValue(0x0020, 0x000D);
	strVal = m_parser.GetTagStringValue(0x0008, 0x1030);
	if (needTransToGbk)
		m_studyInfo.studyDesc = UTF8toA(strVal).c_str();
	else
		m_studyInfo.studyDesc = strVal.c_str();

    m_studyInfo.studyId = m_parser.GetTagStringValue(0x0020, 0x0010);
    m_studyInfo.accessionNumber = m_parser.GetTagStringValue(0x0008, 0x0050);

    tmp = m_parser.GetTagStringValue(0x0008, 0x0020);
    if (tmp.length() == 8)
	{
        m_studyInfo.studyDate = tmp.substr(0, 4);
        m_studyInfo.studyDate += "-";
        m_studyInfo.studyDate += tmp.substr(4, 2);
        m_studyInfo.studyDate += "-";
        m_studyInfo.studyDate += tmp.substr(6);
	}
	else
		m_studyInfo.studyDate = tmp;

    tmp = m_parser.GetTagStringValue(0x0008, 0x0030);
    if (tmp.length() >= 6)
	{
        m_studyInfo.studyTime = tmp.substr(0, 2);
        m_studyInfo.studyTime += ":";
        m_studyInfo.studyTime += tmp.substr(2, 2);
        m_studyInfo.studyTime += ":";
        m_studyInfo.studyTime += tmp.substr(4);
	}
	else
		m_studyInfo.studyTime = tmp;
	
	strVal = m_parser.GetTagStringValue(0x0008, 0x0070);
	if (needTransToGbk)
		m_studyInfo.manufacturer = UTF8toA(strVal).c_str();
	else
		m_studyInfo.manufacturer = strVal.c_str();

	strVal = m_parser.GetTagStringValue(0x0008, 0x0080);
	if (needTransToGbk)
		m_studyInfo.hospitalName = UTF8toA(strVal).c_str();
	else
		m_studyInfo.hospitalName = strVal.c_str();
	
	strVal = m_parser.GetTagStringValue(0x0008, 0x0081);
	if (needTransToGbk)
		m_studyInfo.hospitalAddr = UTF8toA(strVal).c_str();
	else
		m_studyInfo.hospitalAddr = strVal.c_str();

	strVal = m_parser.GetTagStringValue(0x0008, 0x1070);
	if (needTransToGbk)
		m_studyInfo.operatorName = UTF8toA(strVal).c_str();
	else
		m_studyInfo.operatorName = strVal.c_str();

	// Series
    m_seriesInfo.seriesInsUid = m_parser.GetTagStringValue(0x0020, 0x000E);
	strVal = m_parser.GetTagStringValue(0x0008, 0x103E);
	if (needTransToGbk)
		m_seriesInfo.seriesDesc = UTF8toA(strVal).c_str();
	else
		m_seriesInfo.seriesDesc = strVal.c_str();

    tmp = m_parser.GetTagStringValue(0x0008, 0x0021);
    if (tmp.length() == 8)
	{
        m_seriesInfo.seriesDate = tmp.substr(0, 4);
        m_seriesInfo.seriesDate += "-";
        m_seriesInfo.seriesDate += tmp.substr(4, 2);
        m_seriesInfo.seriesDate += "-";
        m_seriesInfo.seriesDate += tmp.substr(6);
	}
	else
		m_seriesInfo.seriesDate = tmp;

    tmp = m_parser.GetTagStringValue(0x0008, 0x0031);
    if (tmp.length() >= 6)
	{
        m_seriesInfo.seriesTime = tmp.substr(0, 2);
        m_seriesInfo.seriesTime += ":";
        m_seriesInfo.seriesTime += tmp.substr(2, 2);
        m_seriesInfo.seriesTime += ":";
        m_seriesInfo.seriesTime += tmp.substr(4);
	}
	else
		m_seriesInfo.seriesTime = tmp;

	m_seriesInfo.seriesNumber = m_parser.GetTagIntValue(0x0020, 0x0011);

	// CT
    m_seriesInfo.kvp = m_parser.GetTagStringValue(0x0018, 0x0060);
    m_seriesInfo.exposureTime = m_parser.GetTagStringValue(0x0018, 0x1150);
    m_seriesInfo.xRayTubeCurrent = m_parser.GetTagStringValue(0x0018, 0x1151);
    m_seriesInfo.exposure = m_parser.GetTagStringValue(0x0018, 0x1152);

	// MR
    m_seriesInfo.percentFOV = m_parser.GetTagStringValue(0x0018, 0x0094);
    m_seriesInfo.TR = m_parser.GetTagStringValue(0x0018, 0x0080);
    m_seriesInfo.TE = m_parser.GetTagStringValue(0x0018, 0x0081);
    m_seriesInfo.FS = m_parser.GetTagStringValue(0x0018, 0x0087);
	m_seriesInfo.amiX = m_parser.GetTagIntValue(0x0018, 0x1310, 0);
	m_seriesInfo.amiY = m_parser.GetTagIntValue(0x0018, 0x1310, 1);
	m_seriesInfo.amjX = m_parser.GetTagIntValue(0x0018, 0x1310, 2);
	m_seriesInfo.amjY = m_parser.GetTagIntValue(0x0018, 0x1310, 3);
    m_seriesInfo.protocolName = m_parser.GetTagStringValue(0x0018, 0x1030);
    m_seriesInfo.scanSequence = m_parser.GetTagStringValue(0x0018, 0x0020);

	// Image
	m_imageInfo.ipX = m_parser.GetTagFloatValue(0x0020, 0x0032, 0);
	m_imageInfo.ipY = m_parser.GetTagFloatValue(0x0020, 0x0032, 1);
	m_imageInfo.ipZ = m_parser.GetTagFloatValue(0x0020, 0x0032, 2);
	m_imageInfo.ioiX = m_parser.GetTagFloatValue(0x0020, 0x0037, 0);
	m_imageInfo.ioiY = m_parser.GetTagFloatValue(0x0020, 0x0037, 1);
	m_imageInfo.ioiZ = m_parser.GetTagFloatValue(0x0020, 0x0037, 2);
	m_imageInfo.iojX = m_parser.GetTagFloatValue(0x0020, 0x0037, 3);
	m_imageInfo.iojY = m_parser.GetTagFloatValue(0x0020, 0x0037, 4);
	m_imageInfo.iojZ = m_parser.GetTagFloatValue(0x0020, 0x0037, 5);
    m_imageInfo.poX = m_parser.GetTagStringValue(0x0020, 0x0020, 0);
    m_imageInfo.poY = m_parser.GetTagStringValue(0x0020, 0x0020, 1);
    m_imageInfo.patPosition = m_parser.GetTagStringValue(0x0018, 0x5100);
    m_imageInfo.sliceThickness = m_parser.GetTagStringValue(0x0018, 0x0050);
    m_imageInfo.sliceLocation = m_parser.GetTagStringValue(0x0020, 0x1041);
	m_imageInfo.samplePerPixel = m_parser.GetTagIntValue(0x0028, 0x0002);

	m_imageInfo.psX = m_parser.GetTagFloatValue(0x0018, 0x1164, 0);
	m_imageInfo.psY = m_parser.GetTagFloatValue(0x0018, 0x1164, 1);
	if (m_imageInfo.psX == 0.0 || m_imageInfo.psY == 0.0) {
		m_imageInfo.psX = m_parser.GetTagFloatValue(0x0028, 0x0030, 0);
		m_imageInfo.psY = m_parser.GetTagFloatValue(0x0028, 0x0030, 1);
	}

	m_imageInfo.bitsAlloc = m_parser.GetTagIntValue(0x0028, 0x0100);
	m_imageInfo.bitsStored = m_parser.GetTagIntValue(0x0028, 0x0101);
	m_imageInfo.hightBit = m_parser.GetTagIntValue(0x0028, 0x0102);
	m_imageInfo.pixelRep = m_parser.GetTagIntValue(0x0028, 0x0103);
	m_imageInfo.defWinCenter = m_parser.GetTagFloatValue(0x0028, 0x1050);
	m_imageInfo.defWinWidth = m_parser.GetTagFloatValue(0x0028, 0x1051);
	if (m_imageInfo.defWinCenter==0.0 && m_imageInfo.defWinWidth==0.0)
	{

	}
	m_imageInfo.rescaleIntercept = m_parser.GetTagFloatValue(0x0028, 0x1052);
	m_imageInfo.rescaleSlope = m_parser.GetTagFloatValue(0x0028, 0x1053);
	m_imageInfo.height = m_parser.GetTagIntValue(0x0028, 0x0010);
	m_imageInfo.width = m_parser.GetTagIntValue(0x0028, 0x0011);
	m_imageInfo.instanceNumber = m_parser.GetTagIntValue(0x0020, 0x0013);

    m_imageInfo.sopInsUid = m_parser.GetTagStringValue(0x0008, 0x0018);
    m_imageInfo.xfer = m_parser.GetTagStringValue(0x0002, 0x0010);
    m_imageInfo.imageType = m_parser.GetTagStringValue(0x0008, 0x0008);
	m_imageInfo.charset = charset;

    tmp = m_parser.GetTagStringValue(0x0008, 0x0023);
    if (tmp.length() == 8)
	{
        m_imageInfo.contentDate = tmp.substr(0, 4);
        m_imageInfo.contentDate += "-";
        m_imageInfo.contentDate += tmp.substr(4, 2);
        m_imageInfo.contentDate += "-";
        m_imageInfo.contentDate += tmp.substr(6);
	}
	else
		m_imageInfo.contentDate = tmp;

    tmp = m_parser.GetTagStringValue(0x0008, 0x0033);
    if (tmp.length() >= 6)
	{
        m_imageInfo.contentTime = tmp.substr(0, 2);
        m_imageInfo.contentTime += ":";
        m_imageInfo.contentTime += tmp.substr(2, 2);
        m_imageInfo.contentTime += ":";
        m_imageInfo.contentTime += tmp.substr(4);
	}
	else
		m_imageInfo.contentTime = tmp;

    tmp = m_parser.GetTagStringValue(0x0008, 0x0022);
    if (tmp.length() == 8)
	{
        m_imageInfo.acquisitionDate = tmp.substr(0, 4);
        m_imageInfo.acquisitionDate += "-";
        m_imageInfo.acquisitionDate += tmp.substr(4, 2);
        m_imageInfo.acquisitionDate += "-";
        m_imageInfo.acquisitionDate += tmp.substr(6);
	}
	else
		m_imageInfo.acquisitionDate = tmp;

    tmp = m_parser.GetTagStringValue(0x0008, 0x0032);
    if (tmp.length() >= 6)
	{
        m_imageInfo.acquisitionTime = tmp.substr(0, 2);
        m_imageInfo.acquisitionTime += ":";
        m_imageInfo.acquisitionTime += tmp.substr(2, 2);
        m_imageInfo.acquisitionTime += ":";
        m_imageInfo.acquisitionTime += tmp.substr(4);
	}
	else
		m_imageInfo.acquisitionTime = tmp;

    if (m_seriesInfo.seriesDate.empty())
		m_seriesInfo.seriesDate = m_imageInfo.acquisitionDate;

    if (m_seriesInfo.seriesTime.empty())
		m_seriesInfo.seriesTime = m_imageInfo.acquisitionTime;

	m_bParserValid = m_parser.HasImage();
	m_fileName = fn;

	Close();

	return TRUE;
}

void CDicomImage::GetDefaultWindow(double& wc, double& ww)
{
	m_parser.GetDefaultWindow(wc, ww);
}

void CDicomImage::GetRange(double& minVal, double& maxVal)
{
	m_parser.GetRange(minVal, maxVal);
}


BOOL CDicomImage::CreateDIB(void*& pdib, int& w, int& h, int wc, int ww, int frame/* = 0*/, bool bneg/* = false*/)
{
	if (pdib)
	{
		delete[]pdib;
		pdib = NULL;
	}

	if (!m_bParserValid)
		ReParseFile();

    return m_parser.CreateDIB(pdib, w, h, wc, ww, frame, bneg);
}


int CDicomImage::GetFrameCount()
{
	return m_parser.GetFrameCount();
}

void CDicomImage::Close()
{
	std::lock_guard<std::mutex> lg(m_parsermtx);
	if (m_parser.GetFrameCount() > 1)
		return;

    m_parser.Close();
	m_bParserValid = FALSE;
}

BOOL CDicomImage::ReParseFile()
{
	std::lock_guard<std::mutex> lg(m_parsermtx);
	if (m_bParserValid)
		return TRUE;

	if (m_fileName.empty())
		return FALSE;

	if (!m_parser.Open(m_fileName))
		return FALSE;

	m_bParserValid = m_parser.IsValid();

	return m_bParserValid;
}


bool CDicomImage::Export(std::string dst, int format)
{	
	if (!IsValid()) ReParseFile();
	return m_parser.Export(dst, format);
}
